package net;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import global.Const;


import java.net.*;
import java.text.SimpleDateFormat;

public class UDPClient {
    private static final int serverPort = Const.SERVER_PORT;
    private static final int clientPort = Const.CLIENT_PORT;
    private static final String serverAddress = Const.SERVER_IP;

    // 发送数据包
    public static void send(JSONObject sendObject) {
        try {
            // 添加时间戳
            sendObject.put("timestamp", System.currentTimeMillis());
            InetAddress inetAddress = InetAddress.getByName(serverAddress);
            // 创建UDP套接字
            DatagramSocket clientSocket = new DatagramSocket();
            // 创建要发送的数据
            byte[] sendData = sendObject.toString().getBytes();
            // 创建数据报
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, inetAddress, serverPort);
            // 发送数据报
            clientSocket.send(sendPacket);
            System.out.printf("\n[%s][UDP][端口:%d]向服务器[%s]发送数据：\n%s\n", getTime(),
                    serverPort, inetAddress, sendObject.toString(JSONWriter.Feature.PrettyFormat));
            // 关闭UDP套接字
            clientSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 接收数据包
    public static JSONObject get(JSONObject jsonObject) {
        JSONObject receiveJson = new JSONObject();
        try {
            // 添加时间戳
            jsonObject.put("timestamp", System.currentTimeMillis());
            // 创建UDP套接字
            DatagramSocket clientSocket = new DatagramSocket();
            // 设置超时时间
            if (Const.TIMEOUT > 0) clientSocket.setSoTimeout(Const.TIMEOUT);
            // 创建要发送的数据
            byte[] sendData = jsonObject.toString().getBytes();
            // 创建数据报
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
                    InetAddress.getByName(Const.SERVER_IP), serverPort);
            // 发送数据报
            clientSocket.send(sendPacket);
            System.out.printf("\n[%s][UDP][端口:%d]向服务器[%s]发送数据：\n%s\n", getTime(),
                    serverPort, serverAddress, jsonObject.toString(JSONWriter.Feature.PrettyFormat));

            // 创建接收数据报
            byte[] receiveData = new byte[10240];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            try {
                clientSocket.receive(receivePacket);
                // 解析接收数据
                receiveJson = JSONObject.parseObject(new String(receivePacket.getData()));
                System.out.printf("\n[%s][UDP][端口:%d]收到服务器[%s]的数据：\n%s\n", getTime(),
                        clientPort, serverAddress, receiveJson.toString(JSONWriter.Feature.PrettyFormat));
            }
            // 超时
            catch (SocketTimeoutException e) {
                receiveJson.put("code", 404);
                receiveJson.put("title", "连接超时");
                receiveJson.put("message", "请稍后重试");
                System.out.printf("\n[%s][UDP][端口:%d]接收数据超时：\n%s\n", getTime(),
                        clientPort, receiveJson.toString(JSONWriter.Feature.PrettyFormat));
                e.printStackTrace();
            }
            clientSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return receiveJson;
    }

    // 接收数据包(不提醒超时)
    public static JSONObject get(JSONObject jsonObject,boolean isPrint) {
        JSONObject receiveJson = new JSONObject();
        try {
            // 添加时间戳
            jsonObject.put("timestamp", System.currentTimeMillis());
            // 创建UDP套接字
            DatagramSocket clientSocket = new DatagramSocket();
            // 设置超时时间
            if (Const.TIMEOUT > 0) clientSocket.setSoTimeout(Const.TIMEOUT);
            // 创建要发送的数据
            byte[] sendData = jsonObject.toString().getBytes();
            // 创建数据报
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
                    InetAddress.getByName(Const.SERVER_IP), serverPort);
            // 发送数据报
            clientSocket.send(sendPacket);
            // 心跳
            System.out.print("heartbeat ");
//            System.out.printf("\n[%s][UDP][端口:%d]向服务器[%s]发送数据：\n%s\n",
//            getTime(), serverPort, serverAddress, jsonObject.toString(JSONWriter.Feature.PrettyFormat));

            // 创建接收数据报
            byte[] receiveData = new byte[10240];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            // 接收数据报
            try {
                clientSocket.receive(receivePacket);
                // 解析接收数据
                receiveJson = JSONObject.parseObject(new String(receivePacket.getData()));
                System.out.printf("\n[%s][UDP][端口:%d]收到服务器[%s]的数据：\n%s\n", getTime(),
                        clientPort, serverAddress, receiveJson.toString(JSONWriter.Feature.PrettyFormat));
            }
            // 超时
            catch (SocketTimeoutException e) {
                receiveJson.put("code", 404);
                receiveJson.put("title", "连接超时");
                receiveJson.put("message", "请稍后重试");
//                System.out.printf("\n[%s][UDP][端口:%d]接收数据超时：\n%s\n", getTime(),
//                clientPort, receiveJson.toString(JSONWriter.Feature.PrettyFormat));
//                e.printStackTrace();
            }
            clientSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return receiveJson;
    }

    // 获取时间
    private static String getTime() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(System.currentTimeMillis());
    }

}

